package com.heima.seckill.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.heima.seckill.exception.GlobalException;
import com.heima.seckill.pojo.Order;
import com.heima.seckill.pojo.SeckillOrder;
import com.heima.seckill.pojo.User;
import com.heima.seckill.rabbitmq.MQSender;
import com.heima.seckill.service.IGoodsService;
import com.heima.seckill.service.IOrderService;
import com.heima.seckill.service.ISeckillOrderService;
import com.heima.seckill.utils.JsonUtil;
import com.heima.seckill.vo.GoodsVo;
import com.heima.seckill.vo.RespBean;
import com.heima.seckill.vo.RespBeanEnum;
import com.heima.seckill.vo.SeckillMessage;
import com.rabbitmq.tools.json.JSONUtil;
import com.wf.captcha.ArithmeticCaptcha;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.internal.util.logging.Log;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;

import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 秒杀
 */
@Slf4j
@Controller
@RequestMapping("/seckill")
public class SeckillController implements InitializingBean {
    @Autowired
    private IGoodsService goodsService;
    @Autowired
    private ISeckillOrderService seckillOrderService;
    @Autowired
    private IOrderService orderService;
    @Autowired
    private RedisTemplate redisTemplate;
    @ Autowired
    private MQSender mqSender;
    private Map<String,Boolean> map=new HashMap<>();
    @Autowired
    private RedisScript<Long> script;


    @PostMapping("/{path}/doSeckill")
    @ResponseBody
    public RespBean doSeckill(@PathVariable String  path, User user, String goodsId) {
        if (user == null) {
            return RespBean.error(RespBeanEnum.SESSION_ERROR);
        }
        ValueOperations valueOperations = redisTemplate.opsForValue();
         //判断秒杀地址是否正确
        boolean check = orderService.checkPath (user,goodsId,path);
        if (!check){
            return RespBean. error(RespBeanEnum .REQUEST_ILLEGAL);
        }


        //判断是否重复抢购
        SeckillOrder seckillOrder = (SeckillOrder) valueOperations.get("order:" + user.getId() + ":" + goodsId);
        if (seckillOrder != null) {  //   订单缓存
            return RespBean.error(RespBeanEnum.REPEATE_ERROR);
        }
        // 内存标记  减少redis 访问
        if (map.get(goodsId)){
            System.out.println(".....1");
            return RespBean.error(RespBeanEnum.EMPTY_STOCK);
        }
        //预减库存
//        Long stock = valueOperations.decrement("seckillGoods:" + goodsId);
        System.out.println(redisTemplate.opsForValue().get("seckillGoods:" + goodsId));
        Long stock = (Long) redisTemplate.execute(script, Collections.singletonList("seckillGoods:" + goodsId),
                Collections.EMPTY_LIST);
        System.out.println("stock----->"+stock);
        if (stock < 0) {
            map.put(goodsId,true);
//            valueOperations.increment("seckillGoods:" + goodsId);// -1 不好看
            System.out.println(".....2");
            return RespBean.error(RespBeanEnum.EMPTY_STOCK);
         }
//        Order order=orderService.seckill(user,goods) ;
        SeckillMessage secmsg = new SeckillMessage(user, goodsId);
        mqSender.sendSeckillMessage(JsonUtil.object2JsonStr(secmsg));
        return RespBean.success(0) ;


        /*
//        model.addAttribute("user", user);
         GoodsVo goods = goodsService.findGoodsVoById(goodsId);
        //判断库存
        if (goods.getStockCount() < 1) {
//            model. addAttribute ("errmsg", RespBeanEnum.EMPTY_STOCK. getMessage());
            return RespBean.error(RespBeanEnum.EMPTY_STOCK);
        }
          //判断是否重复抢购
//          SeckillOrder seckillOrder =
//                    seckillOrderService.getOne (new QueryWrapper<SeckillOrder>() . eq("user_id", user.getId()
//). eq( "goods_id",goodsId));
        SeckillOrder seckillOrder = (SeckillOrder) redisTemplate.opsForValue().get("order:" + user.getId() + ":" + goods.getId());
        if (seckillOrder!=null){  //   订单缓存
//                model. addAttribute("errmsg" , RespBeanEnum.REPEATE_ERROR . getMessage());
                return RespBean.error(RespBeanEnum.REPEATE_ERROR) ;
            }
        Order order=orderService.seckill(user,goods) ;
        System.out.println(order);

        return RespBean.success(order) ;
        */
        }

    /**
     *  获取秒杀结果
     * @return orderId 秒杀成功 -1 秒杀失败  0 排队中
     */
    @GetMapping("/getResult")
    @ResponseBody
    public RespBean getResult(User user ,String goodsId){
        if (user == null) {
            return RespBean.error(RespBeanEnum.SESSION_ERROR);
        }
        Long orderId=seckillOrderService.getResult(user,goodsId);
        System.out.println("orderId------>"+orderId);
        return RespBean.success(orderId);
    }


    /**
     * 获取秒杀地址
     * @param user
     * @param goodsId
     * @param captcha
     * @param request
     * @return
     */

//    @AccessLimit(second = 5, maxCount = 5, needLogin = true)
    @GetMapping(value = "/path")
    @ResponseBody
    public RespBean getPath(User user, Long goodsId, String captcha, HttpServletRequest request) {
        if (user == null) {
            return RespBean.error(RespBeanEnum.SESSION_ERROR);
        }
//   限流 ValueOperations valueOperations = redisTemplate . opsForValue();
//            //限制访问次数，5秒内访间5次
//        String uri = request.getRequestURI();
//        captcha = "0";
//        Integer count = (Integer) valueOperations.get(uri + ":" + user. getId());
//        if (count == null) {
//            valueOperations.set(uri + ":" + user.getId(),1,5,TimeUnit.SECONDS);
//        }else if(count<5){
//            valueOperations.increment( uri + ":" + user.getId());
//        } else {
//            return RespBean.error(RespBeanEnum.ACCESS_LIMIT_REAHCED);
//        }
            //校验验证码
        boolean check = orderService .checkCaptcha(user , goodsId, captcha);
        if (!check) {
            return RespBean.error(RespBeanEnum.ERROR_CAPTCHA);
        }
        String str = orderService. createPath(user,goodsId) ;
        return RespBean. success(str) ;
    }

    /**
     * 获取验证码
     * @param user
     * @param goodsId
     * @param response
     */
    @GetMapping(value = "/captcha")
    public void verifyCode(User user, Long goodsId, HttpServletResponse response) {
        if (user == null || goodsId < 0) {
            throw new GlobalException(RespBeanEnum.REQUEST_ILLEGAL);
        }
        //设置请求头为输出图片的类型
        response.setContentType("image/jpg");
        response.setHeader("Pargam", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        //生成验证码
        ArithmeticCaptcha captcha = new ArithmeticCaptcha(130, 32, 3);
        redisTemplate.opsForValue().set("captcha:" + user.getId() + ":" + goodsId, captcha.text(), 300, TimeUnit.SECONDS);
        try {
            captcha.out(response.getOutputStream());
        } catch (IOException e) {
            log.error("验证码生成失败", e.getMessage());
        }
    }

    /**
     *  系统初始化 ，把商品库存加载到redis
     * @throws Exception
     */

    @Override
    public void afterPropertiesSet() throws Exception {
        List<GoodsVo> list=goodsService.findGoodsVo() ;
        System.out.println("hhhhhhhhhhh");
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        list.forEach(goodsVo ->{
            redisTemplate.opsForValue().set("seckillGoods:" + goodsVo.getId(),goodsVo.getStockCount() );
            map.put(String.valueOf(goodsVo.getId()),false);
            System.out.println("2222222222");
        });

        }
}
